package com.zbangmall.pay.alipay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.zbangmall.pay.alipay.domain.AlipayAppPayRet;
import com.zbangmall.pay.alipay.utils.AlipayConfigurations;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 支付宝支付工具类
 */
public class AlipayAssistant {

	/**
	 * 解析支付宝APP支付回调并验签
	 */
	public static AlipayAppPayRet parseRequest(HttpServletRequest request, boolean enc) throws Exception {
		return (AlipayAppPayRet) convertMap2Bean(getParamsMap(request.getParameterMap(), enc), AlipayAppPayRet.class);
	}

	/**
	 * 是否是关闭订单，如果是关闭订单，注意处理业务，如下发新的商户订单号
	 *
	 * @return true-是 false-不是
	 */
	public static boolean isClosedOrder(String out_trade_no) throws Exception {
		String status = orderStatusQuery(out_trade_no);
		return !"WAIT_BUYER_PAY".equals(status);
	}

	/**
	 * 订单状态查询
	 */
	public static String orderStatusQuery(String out_trade_no) throws Exception {
		// 支付地址
		AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfigurations.GATE_URL,
				// 应用id
				AlipayConfigurations.getAppid(),
				// 私钥
				AlipayConfigurations.getPrivateKey(),
				// 固定值json，参数类型，
				AlipayConstants.FORMAT_JSON,
				// 编码方式
				AlipayConstants.CHARSET_UTF8,
				// 公钥
				AlipayConfigurations.getPublicKey(),
				AlipayConstants.SIGN_TYPE_RSA2);
		AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
		AlipayTradeQueryModel   model   = new AlipayTradeQueryModel();
		model.setOutTradeNo(out_trade_no);
		AlipayTradeQueryResponse response    = alipayClient.execute(request);
		String                   tradeStatus = response.getTradeStatus();
		return tradeStatus;

	}

	/**
	 * 手机网页支付
	 *
	 * @param model      支付信息模型
	 * @param return_url 回跳地址
	 * @param notify_url 异步回调地址
	 */
	public static String preOrder(AlipayTradeWapPayModel model, String return_url, String notify_url) throws Exception {
		return preOrder4Wap(model, return_url, notify_url);
	}

	/**
	 * 手机网页支付
	 *
	 * @return 返回的是一个网页
	 */
	public static String preOrder4Wap(AlipayTradeWapPayModel model, String return_url, String notify_url) throws Exception {
		String html = "";
		AlipayClient alipayClient = new DefaultAlipayClient(
				// 支付地址
				AlipayConfigurations.GATE_URL,
				// 应用id
				AlipayConfigurations.getAppid(),
				// 私钥
				AlipayConfigurations.getPrivateKey(),
				// 固定值json，参数类型，
				AlipayConstants.FORMAT_JSON,
				// 编码方式
				AlipayConstants.CHARSET_UTF8,
				// 公钥
				AlipayConfigurations.getPublicKey(),
				AlipayConstants.SIGN_TYPE_RSA2);
		AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();

		if (return_url != null && !"".equals(return_url)) {
			request.setReturnUrl(return_url);
		}
		request.setNotifyUrl(notify_url);
		request.setBizModel(model);
		AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
		html = response.getBody();
		return html;
	}

	/**
	 * 退款接口
	 */
	public static AlipayTradeRefundResponse refund(AlipayTradeRefundModel model) throws Exception {
		AlipayClient alipayClient = new DefaultAlipayClient(
				// 支付地址
				AlipayConfigurations.GATE_URL,
				// 应用id
				AlipayConfigurations.getAppid(),
				// 私钥
				AlipayConfigurations.getPrivateKey(),
				// 固定值json，参数类型，
				AlipayConstants.FORMAT_JSON,
				// 编码方式
				AlipayConstants.CHARSET_UTF8,
				// 公钥
				AlipayConfigurations.getPublicKey(),
				AlipayConstants.SIGN_TYPE_RSA2);
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
		request.setBizModel(model);
		AlipayTradeRefundResponse response = alipayClient.execute(request);
		if (!response.isSuccess()) {
			throw new RuntimeException("调用失败");
		}
		return response;
	}

	/**
	 * 网页支付
	 *
	 * @param model      支付信息数据模型
	 * @param return_url 回跳地址
	 * @param notify_url 异步回调地址
	 * @return 返回的是一个网页
	 */
	public static String preOrder(AlipayTradePagePayModel model, String return_url, String notify_url) throws Exception {
		return preOrder4Web(model, return_url, notify_url);
	}

	/**
	 * 网页支付
	 */
	public static String preOrder4Web(AlipayTradePagePayModel model, String return_url, String notify_url) throws Exception {
		String html = "";
		// 获得初始化的AlipayClient
		AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfigurations.GATE_URL,
				AlipayConfigurations.getAppid(), AlipayConfigurations.getPrivateKey(), AlipayConstants.FORMAT_JSON,
				AlipayConstants.CHARSET_UTF8, AlipayConfigurations.getPublicKey(), AlipayConstants.SIGN_TYPE_RSA2);
		AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
		if (return_url != null && !"".equals(return_url)) {
			request.setReturnUrl(return_url);
		}
		request.setNotifyUrl(notify_url);
		request.setBizModel(model);
		html = alipayClient.pageExecute(request).getBody();
		return html;
	}

	/**
	 * 支付宝APP支付
	 */
	public static String preOrder(String notifyUrl, AlipayTradeAppPayModel model) throws Exception {
		return preOrder4App(notifyUrl, model);
	}

	/**
	 * 支付宝APP支付
	 */
	public static String preOrder4App(String notifyUrl, AlipayTradeAppPayModel model) throws Exception {
		AlipayClient alipayClient = new DefaultAlipayClient(
				// 支付地址
				AlipayConfigurations.GATE_URL,
				// 应用id
				AlipayConfigurations.getAppid(),
				// 私钥
				AlipayConfigurations.getPrivateKey(),
				// 固定值json，参数类型，
				AlipayConstants.FORMAT_JSON,
				// 编码方式
				AlipayConstants.CHARSET_UTF8,
				// 公钥
				AlipayConfigurations.getPublicKey(),
				AlipayConstants.SIGN_TYPE_RSA2);
		// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
		AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
		request.setBizModel(model);
		if (notifyUrl == null || "".equals(notifyUrl)) {
			throw new RuntimeException("异步通知回调地址不能为空");
		}
		// request.setNotifyUrl(AlipayConfigurations.getNotifyUrl(suffix));
		request.setNotifyUrl(notifyUrl);
		try {
			// 这里和普通的接口调用不同，使用的是sdkExecute
			AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
			return response.getBody();
		} catch (AlipayApiException e) {
			e.printStackTrace();
			throw e;
		}
	}

	/**
	 * 支付宝APP预支付
	 */
	public static String preOrder(AlipayTradeAppPayModel model, String suffix) throws Exception {
		return preOrder4App(model, suffix);
	}


	/**
	 * 支付宝生成APP订单
	 */
	public static String preOrder4App(AlipayTradeAppPayModel model, String suffix) throws Exception {
		// 实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(
				// 支付地址
				AlipayConfigurations.GATE_URL,
				// 应用id
				AlipayConfigurations.getAppid(),
				// 私钥
				AlipayConfigurations.getPrivateKey(),
				// 固定值json，参数类型，
				AlipayConstants.FORMAT_JSON,
				// 编码方式
				AlipayConstants.CHARSET_UTF8,
				// 公钥
				AlipayConfigurations.getPublicKey(),
				AlipayConstants.SIGN_TYPE_RSA2);
		// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
		AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
		request.setBizModel(model);
		if (suffix == null || "".equals(suffix)) {
			throw new RuntimeException("回调地址后缀不能为空");
		}
		request.setNotifyUrl(AlipayConfigurations.getNotifyUrl(suffix));
		try {
			// 这里和普通的接口调用不同，使用的是sdkExecute
			AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
			return response.getBody();
		} catch (AlipayApiException e) {
			e.printStackTrace();
			throw e;
		}
	}

	/**
	 * 将Map转换成对象
	 */
	public static Object convertMap2Bean(Map<String, String> map, Class<?> clazz) throws Exception {
		Map<String, Object> objMap = new TreeMap<>();
		//预处理map，将里面的json字符串字段转换成对象
		Set<String> keys = map.keySet();
		for (String key : keys) {
			String str = map.get(key);
			try {
				//如果是JSON字符串，则转换成对象，再添加到objMap中
				objMap.put(key, JSON.parse(str));
			} catch (JSONException e) {
				//如果不是JSON字符串，则直接添加到objMap中
				objMap.put(key, str);
			} catch (Exception e) {
				//其余错误抛出
				e.printStackTrace();
			}
		}
		Object obj = JSON.parseObject(JSON.toJSONString(objMap), clazz);
		return obj;
	}

	/**
	 * 验签并返回参数
	 */
	@SuppressWarnings("rawtypes")
	public static Map<String, String> getParamsMap(Map requestParamterMap, boolean enc) throws Exception {
		Map<String, String> params = new HashMap<>();

		for (Iterator iter = requestParamterMap.keySet().iterator(); iter.hasNext(); ) {
			String   name     = (String) iter.next();
			String[] values   = (String[]) requestParamterMap.get(name);
			String   valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			if (enc) {
				valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			}
			params.put(name, valueStr);
		}

		// 切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
		// boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String
		// publicKey, String charset, String sign_type)
		boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfigurations.getPublicKey(), AlipayConstants.CHARSET_UTF8, "RSA2");
		if (!flag) {
			throw new RuntimeException("验签失败");
		}
		return params;
	}

	/**
	 * 异步回调返回参数
	 */
	public static String echo() {
		return "success";
	}

}
